/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-06-29     17247       the first version
 */
#include "uart_protocol.h"
#include <rtthread.h>
#include <string.h>

// 声明uart0_send函数，避免重复包含uart0.c
extern void uart0_send(const void *data, rt_size_t size);

// 定义全局变量
FrameData global_frame_data;
// 存储解析数据的独立变量
rt_uint8_t global_exist_info = 0;          // 存在信息
rt_uint8_t global_motion_info = 0;         // 运动信息
rt_uint8_t global_body_movement = 0;       // 体动参数
rt_uint16_t global_human_distance = 0;     // 人体距离
rt_uint8_t global_heart_rate_value = 0;    // 心率数值
rt_int16_t global_human_position_x = 0;    // 人体方位 X
rt_int16_t global_human_position_y = 0;    // 人体方位 Y
rt_int16_t global_human_position_z = 0;    // 人体方位 Z
rt_uint8_t global_switch_func_status = 0;  // 开关人体存在功能状态
rt_uint8_t global_breathing_info = 0;      // 呼吸信息
rt_uint8_t global_breathing_value = 0;     // 呼吸数值
rt_uint8_t global_breathing_wave[5] = { 0 }; // 呼吸波形数据
rt_uint8_t global_bed_status = 0;                          // 入床/离床状态
rt_uint16_t global_awake_duration = 0;                     // 清醒时长
rt_uint16_t global_light_sleep_duration = 0;               // 浅睡时长
rt_uint16_t global_deep_sleep_duration = 0;                // 深睡时长
rt_uint8_t global_sleep_quality_score = 0;                 // 睡眠质量评分
rt_uint8_t global_sleep_status = 0;                        // 睡眠状态
rt_uint8_t global_sleep_comprehensive_data[8] = { 0 };     // 睡眠综合状态数据
rt_uint8_t global_sleep_analysis_data[12] = { 0 };         // 睡眠质量分析数据
/**
 * @brief 计算校验码
 */
rt_uint8_t calculate_checksum(const rt_uint8_t *data, rt_size_t len)
{
    rt_uint8_t checksum = 0;
    for (rt_size_t i = 0; i < len; i++)
    {
        checksum += data[i];
    }
    return checksum;
}

/**
 * @brief 解析数据帧
 */
/**
 * @brief 解析数据帧
 */
void parse_frame(const rt_uint8_t *buffer, rt_size_t length)
{
    if (length < 8)
    {
        rt_kprintf("[UART0] Frame too short: %d\n", length);
        return;
    }

    // 检查帧头和帧尾
    if (buffer[0] != FRAME_HEADER_1 || buffer[1] != FRAME_HEADER_2 || buffer[length - 2] != FRAME_TAIL_1
            || buffer[length - 1] != FRAME_TAIL_2)
    {
        rt_kprintf("[UART0] Frame header/tail mismatch: 0x%02X 0x%02X ... 0x%02X 0x%02X\n", 
                  buffer[0], buffer[1], buffer[length-2], buffer[length-1]);
        return;
    }

    // 提取控制字、命令字、数据长度
    rt_uint8_t ctrl = buffer[2];
    rt_uint8_t cmd = buffer[3];
    rt_uint16_t data_len = (buffer[4] << 8) | buffer[5];

    rt_kprintf("[UART0] Parsing frame: ctrl=0x%02X, cmd=0x%02X, len=%d\n", ctrl, cmd, data_len);

    // 校验长度
    if (length != (6 + data_len + 1 + 2))
    {
        rt_kprintf("[UART0] Length mismatch: expected=%d, actual=%d\n", 6 + data_len + 1 + 2, length);
        return;
    }

    const rt_uint8_t *data_ptr = &buffer[6];

    // 校验码验证
    rt_uint8_t checksum = buffer[6 + data_len];
    rt_uint8_t calculated_checksum = calculate_checksum(buffer, 6 + data_len);
    if (checksum != calculated_checksum)
    {
        rt_kprintf("[UART0] Checksum mismatch: received=0x%02X, calculated=0x%02X\n", checksum, calculated_checksum);
        return;
    }

    rt_kprintf("[UART0] Frame validation passed, processing data...\n");

    // 保存到全局变量
    global_frame_data.ctrl = ctrl;
    global_frame_data.cmd = cmd;
    global_frame_data.len = data_len;
    rt_memcpy(global_frame_data.data, data_ptr, data_len);

    switch (ctrl)
    {
    case CTRL_SWITCH_FUNC:
        if (cmd == 0x00)
        {
            global_switch_func_status = data_ptr[0];
            rt_kprintf("[UART0] Updated switch_func_status: %d\n", global_switch_func_status);
            // 回复功能：收到开关人体存在功能设置命令，回发应答帧
            send_reply_frame(ctrl, cmd, data_ptr, data_len);
        }
        break;

    case CTRL_HUMAN_EXIST:
        switch (cmd)
        {
        case 0x01: // 存在信息主动上报
            global_exist_info = data_ptr[0];
            rt_kprintf("[UART0] Updated exist_info: %d\n", global_exist_info);
            break;
        case 0x10: // 查询存在信息命令（假设0x10为查询命令）
            // 回复功能：主机查询存在信息，回发当前状态
            send_reply_frame(ctrl, 0x01, &global_exist_info, 1);
            break;
        case 0x02: // 运动信息主动上报
            global_motion_info = data_ptr[0];
            rt_kprintf("[UART0] Updated motion_info: %d\n", global_motion_info);
            break;
        case 0x03: // 体动参数主动上报
            global_body_movement = data_ptr[0];
            rt_kprintf("[UART0] Updated body_movement: %d\n", global_body_movement);
            break;
        case 0x04: // 人体距离主动上报
            global_human_distance = (data_ptr[0] << 8) | data_ptr[1];
            rt_kprintf("[UART0] Updated human_distance: %d\n", global_human_distance);
            break;
        case 0x05: // 人体方位主动上报
            global_human_position_x = (data_ptr[0] << 8) | data_ptr[1];
            global_human_position_y = (data_ptr[2] << 8) | data_ptr[3];
            global_human_position_z = (data_ptr[4] << 8) | data_ptr[5];

            // 负数补码处理
            global_human_position_x =
                    (global_human_position_x & 0x8000) ?
                            -(0xFFFF - global_human_position_x + 1) : global_human_position_x;
            global_human_position_y =
                    (global_human_position_y & 0x8000) ?
                            -(0xFFFF - global_human_position_y + 1) : global_human_position_y;
            global_human_position_z =
                    (global_human_position_z & 0x8000) ?
                            -(0xFFFF - global_human_position_z + 1) : global_human_position_z;
            rt_kprintf("[UART0] Updated position: x=%d, y=%d, z=%d\n", 
                      global_human_position_x, global_human_position_y, global_human_position_z);
            break;
        default:
            rt_kprintf("[UART0] Unknown HUMAN_EXIST command: 0x%02X\n", cmd);
            break;
        }
        break;

    case CTRL_HEART_RATE:
        switch (cmd)
        {
        case CMD_HEART_RATE_VALUE:  // 心率数值上报
            if (data_len == 1 && data_ptr[0] >= 60 && data_ptr[0] <= 120)
            {
                global_heart_rate_value = data_ptr[0];
                rt_kprintf("[UART0] Updated heart_rate: %d\n", global_heart_rate_value);
            }
            else
            {
                rt_kprintf("[UART0] Invalid heart rate value: %d (len=%d)\n", data_ptr[0], data_len);
            }
            break;

        default:
            rt_kprintf("[UART0] Unknown HEART_RATE command: 0x%02X\n", cmd);
            break;
        }
        break;

    case CTRL_BREATHING:
        switch (cmd)
        {
        case CMD_BREATHING_INFO:  // 呼吸信息上报
            if (data_len == 1)
            {
                global_breathing_info = data_ptr[0];
                rt_kprintf("[UART0] Updated breathing_info: %d\n", global_breathing_info);
            }
            break;

        case CMD_BREATHING_VALUE:  // 呼吸数值上报
            if (data_len == 1 && data_ptr[0] <= 35)
            {
                global_breathing_value = data_ptr[0];
                rt_kprintf("[UART0] Updated breathing_value: %d\n", global_breathing_value);
            }
            else
            {
                rt_kprintf("[UART0] Invalid breathing value: %d (len=%d)\n", data_ptr[0], data_len);
            }
            break;

        case CMD_BREATHING_WAVE:  // 呼吸波形上报
            if (data_len == 5)
            {
                rt_memcpy(global_breathing_wave, data_ptr, data_len);
                rt_kprintf("[UART0] Updated breathing_wave\n");
            }
            break;

        default:
            rt_kprintf("[UART0] Unknown BREATHING command: 0x%02X\n", cmd);
            break;
        }
        break;
    case CTRL_BED_STATUS:
        switch (cmd)
        {
        case CMD_BED_STATUS:
            global_bed_status = data_ptr[0];
            break;
        default:
            break;
        }
        break;

    case CTRL_SLEEP_STATUS:
        switch (cmd)
        {
        case CMD_SLEEP_STATUS:
            global_sleep_status = data_ptr[0];
            break;
        default:
            break;
        }
        break;

    case CTRL_AWAKE_DURATION:
        if (cmd == CMD_AWAKE_DURATION)
        {
            global_awake_duration = (data_ptr[0] << 8) | data_ptr[1];
        }
        break;

    case CTRL_LIGHT_SLEEP_DURATION:
        if (cmd == CMD_LIGHT_SLEEP_DURATION)
        {
            global_light_sleep_duration = (data_ptr[0] << 8) | data_ptr[1];
        }
        break;

    case CTRL_DEEP_SLEEP_DURATION:
        if (cmd == CMD_DEEP_SLEEP_DURATION)
        {
            global_deep_sleep_duration = (data_ptr[0] << 8) | data_ptr[1];
        }
        break;

    case CTRL_SLEEP_QUALITY_SCORE:
        if (cmd == CMD_SLEEP_QUALITY_SCORE)
        {
            global_sleep_quality_score = data_ptr[0];
        }
        break;

    case CTRL_SLEEP_COMPREHENSIVE:
        if (cmd == CMD_SLEEP_COMPREHENSIVE)
        {
            rt_memcpy(global_sleep_comprehensive_data, data_ptr, data_len);
        }
        break;

    case CTRL_SLEEP_ANALYSIS:
        if (cmd == CMD_SLEEP_ANALYSIS)
        {
            rt_memcpy(global_sleep_analysis_data, data_ptr, data_len);
        }
        break;

    default:
        rt_kprintf("[UART0] Unknown control word: 0x%02X\n", ctrl);
        break;
    }
}
const FrameData* get_global_frame_data(void)
{
    return &global_frame_data;
}

/**
 * @brief 发送回复帧（// 回复功能）
 * @param ctrl 控制字
 * @param cmd  命令字
 * @param data 数据指针
 * @param data_len 数据长度
 */
void send_reply_frame(rt_uint8_t ctrl, rt_uint8_t cmd, const rt_uint8_t *data, rt_uint16_t data_len)
{
    rt_uint8_t frame[256];
    rt_size_t offset = 0;
    frame[offset++] = FRAME_HEADER_1;
    frame[offset++] = FRAME_HEADER_2;
    frame[offset++] = ctrl;
    frame[offset++] = cmd;
    frame[offset++] = (data_len >> 8) & 0xFF;
    frame[offset++] = data_len & 0xFF;
    if (data_len > 0 && data != RT_NULL)
    {
        rt_memcpy(&frame[offset], data, data_len);
        offset += data_len;
    }
    frame[offset++] = calculate_checksum(frame, 6 + data_len);
    frame[offset++] = FRAME_TAIL_1;
    frame[offset++] = FRAME_TAIL_2;
    uart0_send(frame, offset); // 通过UART0发送
}
